local dewdrop = AceLibrary("Dewdrop-2.0")
local L = AceLibrary("AceLocale-2.2"):new("SpeedFu")

SpeedFu = AceLibrary("AceAddon-2.0"):new("FuBarPlugin-2.0", "AceConsole-2.0", "AceDB-2.0")
SpeedFu.hasIcon = "Interface\\Icons\\Ability_Rogue_Sprint.blp"

local optionsTable = {
	type = 'group',
	args = {
		digit = {
			order = 3,
			type = 'toggle',
			name = L["MENU_DIGIT"],
			desc = L["TOOLTIP_DIGIT"],
			set = "ToggleDigit",
			get = "GetDigit",
		}
	}
}

SpeedFu.blizzardTooltip = true
SpeedFu.OnMenuRequest = optionsTable
SpeedFu:RegisterChatCommand( { "/speedfu" }, optionsTable )

local FREQUENCY = 0.5
local frame

local zoneBaseRate = {
			Durotar = 5287.5,
			Mulgore = 5137.5,
			Barrens = 10133.34,
			Kalimdor = 36799.8,
			Azeroth = 40741.2,
			Alterac = 2800.003,
			Arathi = 3600.003,
			Badlands = 2487.5,
			BlastedLands = 3350,
			Tirisfal = 4518.75,
			Silverpine = 4200,
			WesternPlaguelands = 4299.997,
			EasternPlaguelands = 3870.83,
			Hilsbrad = 3200,
			Hinterlands = 3850,
			DunMorogh = 4925,
			SearingGorge = 2231.253,
			BurningSteppes = 2929.163,
			Elwynn = 3470.84,
			DeadwindPass = 2499.997,
			Duskwood = 2700.003,
			LochModan = 2758.33,
			Redridge = 2170.84,
			Stranglethorn = 6381.25,
			SwampOfSorrows = 2293.75,
			Westfall = 3500.003,
			Wetlands = 4135.417,
			Teldrassil = 5091.66,
			Darkshore = 6550,
			Ashenvale = 5766.67,
			ThousandNeedles = 4399.997,
			StonetalonMountains = 4883.33,
			Desolace = 4495.83,
			Feralas = 6950,
			Dustwallow = 5250,
			Tanaris = 6900,
			Aszhara = 5070.84,
			Felwood = 5750,
			UngoroCrater = 3700.003,
			Moonglade = 2308.33,
			Silithus = 3483.334,
			Winterspring = 7100.003,
			Stormwind = 1344.2694,
			Ogrimmar = 1402.61,
			Ironforge = 790.629,
			ThunderBluff = 1043.75,
			Darnassis = 1058.33,
			Undercity = 959.3754,
			AlteracValley = 4237.5,
			WarsongGulch = 1145.837,
			ArathiBasin = 1756.247,
			EversongWoods = 4925,
			Ghostlands = 3300,
			AzuremystIsle = 4070.8,
			Hellfire = 5164.58,
			Expansion01 = 17464.04,
			Zangarmarsh = 5027.08,
			TheExodar = 1056.7,
			ShadowmoonValley = 5500,
			BladesEdgeMountains = 5425,
			BloodmystIsle = 3262.5,
			Nagrand = 5524.97,
			TerokkarForest = 5400,
			Netherstorm = 5574.9967,
			SilvermoonCity = 1211.46,
			ShattrathCity = 1306.25,
			NetherstormArena = 2270.837,
			Sunwell = 3327.09,
}

function SpeedFu:OnInitialize()

	if not frame then frame = CreateFrame("Frame") end
	frame:SetScript("OnEvent",function(frame,event,...) self[event](self,...) end)
	frame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
	
	frame:Hide()
	frame:SetScript("OnUpdate", self.UpdateSpeed)
	
	self:RegisterDB("FuBar_SpeedDB")
	
	self.vars = {}
	self.text = "???%"
	
end

function SpeedFu:OnEnable()
	frame:Show()
end

function SpeedFu:OnDisable()
	frame:Hide()
end

-- This will be called from FuBar.
function SpeedFu:OnTextUpdate()
	self:SetText(self.text)
end

function SpeedFu:ToggleDigit()
	self.db.profile.digit = not self.db.profile.digit
end

function SpeedFu:GetDigit()
	return self.db.profile.digit
end

function SpeedFu:ZONE_CHANGED_NEW_AREA()
	if not WorldMapFrame:IsShown() then
		SetMapToCurrentZone()
		self.vars.lastPos = nil
	end

end

local difference = 0
function SpeedFu.UpdateSpeed(frame,elapsed)
	difference = difference + elapsed
	if difference < FREQUENCY then
		return
	end
	
	local self = SpeedFu

	-- Initialize.
	if (self.vars.lastPos == nil) then
		self.vars.lastTime = time()
		self.vars.iDeltaTime = 0
		self.vars.fSpeed = 0.0
		self.vars.fSpeedDist = 0.0
		self.vars.CurrPos = {}
		self.vars.lastPos = {}
		self.vars.lastPos.m, self.vars.lastPos.x, self.vars.lastPos.y = GetMapInfo(), GetPlayerMapPosition("player")
	end
	
	self.vars.iDeltaTime = self.vars.iDeltaTime + difference;
	self.vars.CurrPos.m, self.vars.CurrPos.x, self.vars.CurrPos.y = GetMapInfo(), GetPlayerMapPosition("player")
	
	if ((self.vars.CurrPos.x == 0) and (self.vars.CurrPos.y == 0)) or (self.vars.lastPos.m ~= self.vars.CurrPos.m) then
		self.vars.fSpeed = "-"
		self.vars.fSpeedDist = 0.0
		self.vars.iDeltaTime = 0.0
	else
		local dist = math.sqrt(
			((self.vars.lastPos.x - self.vars.CurrPos.x) * (self.vars.lastPos.x - self.vars.CurrPos.x) * 2.25 ) +
			((self.vars.lastPos.y - self.vars.CurrPos.y) * (self.vars.lastPos.y - self.vars.CurrPos.y))
			)
		
		self.vars.fSpeedDist = self.vars.fSpeedDist + dist
		
		if (self.vars.iDeltaTime >= .5) then
			local zone = self.vars.CurrPos.m
			local displacement = (self.vars.fSpeedDist / self.vars.iDeltaTime)
			local baserate
			
			baserate = zoneBaseRate[zone]
			
			if (baserate ~= nil and baserate ~= 0) then
				self.vars.fSpeed = self:Round( (displacement / (10.5 / baserate)) * 100)
				self.vars.fSpeedDist = 0.0
				self.vars.iDeltaTime = 0.0
			else
				self.vars.fSpeed = "-"
				self.vars.fSpeedDist = 0.0
				self.vars.iDeltaTime = 0.0
			end
		end -- if (self.vars.iDeltaTime >= .5) 
	end -- if  ((self.vars.CurrPos.x == 0) and (self.vars.CurrPos.y == 0)) 
	
	self.vars.lastPos.m = self.vars.CurrPos.m
	self.vars.lastPos.x = self.vars.CurrPos.x
	self.vars.lastPos.y = self.vars.CurrPos.y
	
	local text;
	if self.vars.fSpeed == nil or self.vars.fSpeed == "-" then
		text = "???%"
	else
		if self.db.profile.digit then
			text = string.format("%03d", self.vars.fSpeed) .. "%"
		else
			text = self.vars.fSpeed .. "%"
		end
		if self.vars.fSpeed == 100 then
			text = string.format("|cffffffff%s|r", text)
		elseif self.vars.fSpeed > 100 then
			text = string.format("|cff00ff00%s|r", text)
		elseif self.vars.fSpeed < 100 then
			text = string.format("|cffff0000%s|r", text)
		end
	end
	
	self.text = text
	
	self:Update()
	
	difference = 0
end

function SpeedFu:Round(x)
	if(x - floor(x) > 0.5) then
		x = floor(x + 0.5)
	else
		if(x - floor(x) > 0.25) then
			x = floor(x) + 0.5
		else x = floor(x)
		end
	end
	return x
end
